home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / msdos / ati15khz.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  27KB  |  883 lines

  1. #include "mamalleg.h"
  2. #include "driver.h"
  3. #include <pc.h>
  4. #include <conio.h>
  5. #include <sys/farptr.h>
  6. #include <go32.h>
  7. #include <time.h>
  8. #include <math.h>
  9. #include "TwkUser.h"
  10. #include "gen15khz.h"
  11. #include "ati15khz.h"
  12.  
  13.  
  14.  
  15. extern int center_x;
  16. extern int center_y;
  17. extern int use_triplebuf;
  18.  
  19. /* Save values */
  20. static int DSPSet;
  21. static int SaveDSPOnOff;
  22. static int SaveDSPConfig;
  23.  
  24. /* Currently -
  25.     only ATI cards based on the Mach64 chipset which have an internal clock/DAC
  26.     are supported (see note below)*/
  27.  
  28. /* Tested on a 3D Rage Pro II+ , 3D Rage Charger and Xpert@Play */
  29.  
  30. /* NOTE: There are 2 versions of this driver, */
  31. /* one reprograms the clock to generate the mode (original driver) */
  32. /* the other doubles the scan line to generate the mode */
  33.  
  34. /* The first version's display is smaller (and therefore faster), but only works on */
  35. /* cards which have internal clocks */
  36. /* The second should work on all Mach64 based cards */
  37.  
  38. /* Comment out the following line to use the no-clock programming driver */
  39. #define ATI_PROGRAM_CLOCK
  40.  
  41.  
  42. /* Type of clock */
  43. char *mach64ClockTypeTable[] =
  44. {
  45.     "ATI18818-0",
  46.     "ATI18818-1/ICS2595",
  47.     "STG1703",
  48.     "CH8398",
  49.     "Internal",
  50.     "AT&T20C408",
  51.     "IBM-RGB514",
  52. };
  53.  
  54. /* the clock info we need for integrated DACs */
  55. static int RefFreq;     /* Reference frequency for clock */
  56. static int RefDivider;  /* Reference divider for clock */
  57. static int MinFreq;     /* Minimum frequency of clock */
  58. static int MaxFreq;     /* Maximum frequency of clock */
  59. static int VRAMMemClk;  /* Speed of video RAM clock */
  60. static int CXClk;       /* ID of clock we're going to program */
  61. static int MemSize;     /* Memory on the card */
  62. static int MemType;     /* Type of memory on the card */
  63. static int ChipID;      /* ID of chip on card */
  64. static int ChipRev;     /* revision of chip on card */
  65. static int ChipType;    /* what we decide in our wisdom the chip is */
  66.  
  67.  
  68.  
  69. /* the MACH64 registers we're interested in */
  70. static int _mach64_clock_reg;
  71. static int _mach64_gen_cntrl;
  72. static int _mach64_off_pitch;
  73. static int _mach64_dac_cntl;
  74. static int _mach64_config_stat0;
  75. static int _mach64_crtc_h_total;
  76. static int _mach64_crtc_h_sync;
  77. static int _mach64_crtc_v_total;
  78. static int _mach64_crtc_v_sync;
  79. static int _mach64_crtc_v_line;
  80. static int _mach64_over_left_right;
  81. static int _mach64_over_top_bott;
  82. static int _mach64_mem_cntl;
  83. static int _mach64_chip_id;
  84. static int _mach64_dsp_config;
  85. static int _mach64_dsp_on_off;
  86.  
  87.  
  88. /*see if we've really got an ATI card with a Mach64 chipset  */
  89. int detectati(void)
  90. {
  91.     __dpmi_regs r;
  92.     int scratch_reg;
  93.     unsigned long old;
  94.     char bios_data[BIOS_DATA_SIZE];
  95.     unsigned short *sbios_data = (unsigned short *)bios_data;
  96.     int ROM_Table_Offset;
  97.     int Freq_Table_Ptr;
  98.     int Clock_Type;
  99.  
  100.  
  101.  
  102.     /* query mach64 BIOS for the I/O base address */
  103.     r.x.ax = 0xA012;
  104.     r.x.cx = 0;
  105.     __dpmi_int (0x10, &r);
  106.  
  107.     if (r.h.ah)
  108.         return 0;
  109.  
  110.     /* test scratch register to confirm we have a mach64 */
  111.     scratch_reg = get_mach64_port (r.x.cx, r.x.dx, 0x11, 0x21);
  112.  
  113.     old = inportl(scratch_reg);
  114.  
  115.     outportl (scratch_reg, 0x55555555);
  116.     if (inportl (scratch_reg) != 0x55555555)
  117.     {
  118.         outportl (scratch_reg, old);
  119.         logerror("15.75KHz: Not Mach64 Chipset\n");
  120.         return 0;
  121.     }
  122.  
  123.     outportl (scratch_reg, 0xAAAAAAAA);
  124.     if (inportl (scratch_reg) != 0xAAAAAAAA)
  125.     {
  126.         outportl (scratch_reg, old);
  127.         logerror("15.75KHz: Not Mach64 Chipset\n");
  128.         return 0;
  129.     }
  130.  
  131.     outportl (scratch_reg, old);
  132.  
  133.     /* get info from the ATI BIOS */
  134.     dosmemget (BIOS_DATA_BASE, BIOS_DATA_SIZE, bios_data);
  135.     ROM_Table_Offset = sbios_data[0x48 >> 1];
  136.     Freq_Table_Ptr = sbios_data[(ROM_Table_Offset >> 1) + 8];
  137.     Clock_Type = bios_data[Freq_Table_Ptr];
  138.     CXClk = bios_data[Freq_Table_Ptr + 6];
  139.     RefFreq = sbios_data[(Freq_Table_Ptr >> 1) + 4];
  140.     RefDivider = sbios_data[(Freq_Table_Ptr >> 1) + 5];
  141.     MinFreq = sbios_data[(Freq_Table_Ptr >> 1) + 1];
  142.     MaxFreq = sbios_data[(Freq_Table_Ptr >> 1) + 2];
  143.     VRAMMemClk = sbios_data[(Freq_Table_Ptr >> 1) + 9];
  144.     logerror("15.75KHz: type of MACH64 clk: %s (%d)\n", mach64ClockTypeTable[Clock_Type], Clock_Type);
  145.     logerror("15.75KHz: MACH64 ref Freq:%d\n", RefFreq);
  146.     logerror("15.75KHz: MACH64 ref Div:%d\n", RefDivider);
  147.     logerror("15.75KHz: MACH64 min Freq:%d\n", MinFreq);
  148.     logerror("15.75KHz: MACH64 max Freq:%d\n", MaxFreq);
  149.     logerror("15.75KHz: MACH64 Mem Clk %d\n", VRAMMemClk);
  150.  
  151.  
  152. /*Get some useful registers while we're here  */
  153.  
  154. /*
  155. M+000h/02ECh D(R/W):  Crtc_H_Total_Disp
  156. bit   0-7  Crtc_H_Total. Horizontal Total in character clocks (8 pixel units)
  157.     16-23  Crtc_H_Disp. Horizontal Display End in character clocks.
  158. */
  159.  
  160.     _mach64_crtc_h_total = get_mach64_port (r.x.cx, r.x.dx, 0x00, 0x00);
  161. /*
  162. M+004h/06ECh D(R/W):  Crtc_H_Sync_Strt_Wid
  163. bit   0-7  Crtc_H_Sync_Strt. Horizontal Sync Start in character clocks (8
  164.            pixel units)
  165.      8-10  Crtc_H_Sync_Dly. Horizontal Sync Start delay in pixels
  166.     16-20  Crtc_H_Sync_Wid. Horizontal Sync Width in character clocks
  167.        21  Crtc_H_Sync_Pol. Horizontal Sync Polarity
  168. */
  169.     _mach64_crtc_h_sync = get_mach64_port (r.x.cx, r.x.dx, 0x01, 0x01);
  170. /*
  171. M+008h/0AECh D(R/W):  Crtc_V_Total_Disp
  172. bit  0-10  Crtc_V_Total. Vertical Total
  173.     16-26  Crtc_V_Disp. Vertical Displayed End
  174. */
  175.     _mach64_crtc_v_total = get_mach64_port (r.x.cx, r.x.dx, 0x02, 0x02);
  176. /*
  177. M+00Ch/0EECh D(R/W):  Crtc_V_Sync_Strt_Wid
  178. bit  0-10  Crtc_V_Sync_Strt. Vertical Sync Start
  179.     16-20  Crtc_V_Sync_Wid. Vertical Sync Width
  180.        21  Crtc_V_Sync_Pol. Vertical Sync Polarity
  181. */
  182.     _mach64_crtc_v_sync = get_mach64_port (r.x.cx, r.x.dx, 0x03, 0x03);
  183.  
  184. /*
  185. M+010h/12ECh D(R/W):  Crtc_Vline_Crnt_Vline
  186. bit  0-10  The line at which Vertical Line interrupt is triggered
  187.     16-26  (R) Crtc_Crnt_Vline. The line currently being displayed
  188. */
  189.     _mach64_crtc_v_line = get_mach64_port (r.x.cx, r.x.dx, 0x04, 0x04);
  190.  
  191. /*
  192. M+014h/16ECh D(R/W):  Crtc_Off_Pitch
  193. bit  0-19  Crtc_Offset. Display Start Address in units of 8 bytes.
  194.     22-31  Crtc_Pitch. Display pitch in units of 8 pixels
  195. */
  196.     _mach64_off_pitch = get_mach64_port (r.x.cx, r.x.dx, 0x05, 0x05);
  197.  
  198. /*
  199. M+01Ch/1EECh D(R/W):  Crtc_Gen_Cntl
  200. bit     0  Crtc_Dbl_Scan_En. Enables double scan
  201.         1  Crtc_Interlace_En. Enables interlace.
  202.         2  Crtc_Hsync_Dis. Disables Horizontal Sync output
  203.         3  Crtc_Vsync_Dis. Disables Vertical Sync output
  204.         4  Crtc_Csync_En. Enable composite sync on Horizontal Sync output
  205.         5  Crtc_Pic_By_2_En. CRTC advances 2 pixels per pixel clock
  206.      8-10  Crtc_Pix_Width. Displayed bits/pixel: 1: 4bpp, 2: 8bpp, 3: 15bpp
  207.             (5:5:5), 4: 16bpp (5:6:5), 5: 24bpp(undoc), 6: 32bpp
  208.        11  Crtc_Byte_Pix_Order. Pixel order within each byte (4bpp).
  209.             0: High nibble displayed first, 1: low nibble displayed first
  210.     16-19  Crtc_Fifo_Lwm. Low Water Mark of the 16entry deep display FIFO.
  211.            Only used in DRAM configurations. The minimum number of entries
  212.            remaining in the FIFO before the CRTC starts refilling. Ideally
  213.            should be set to the lowest number that gives a stable display.
  214.        24  Crtc_Ext_Disp_En. 1:Extended display mode , 0:VGA display mode
  215.        25  Crtc_En. Enables CRTC if set, resets if clear
  216.  
  217. */
  218.  
  219.     _mach64_gen_cntrl = get_mach64_port (r.x.cx, r.x.dx, 0x07, 0x07);
  220.  
  221. /* DSP registers  */
  222. /* No reliable information available about these....  */
  223.     _mach64_dsp_config = get_mach64_port (r.x.cx, r.x.dx, 0x08, 0x08);
  224.     _mach64_dsp_on_off = get_mach64_port (r.x.cx, r.x.dx, 0x09, 0x09);
  225.  
  226.  
  227. /*
  228. M+090h/4AECh D(R/W):  Clock_Cntl
  229. bit   0-3  Clock_Sel. Clock select bit 0-3. Output to the clock chip
  230.       4-5  Clock_Div. Internal clock divider. 0: no div, 1: /2, 2: /4
  231.         6  (W) Clock_Strobe. Connected to the strobe or clk input on
  232.             programmable clock chips
  233.         7  Clock_Serial_Data. Data I/O for programmable clock chips
  234. */
  235.     _mach64_clock_reg = get_mach64_port (r.x.cx, r.x.dx, 0x12, 0x24);
  236.  
  237. /*
  238. M+0C4h/62ECh D(R/W):  Dac_Cntl
  239. bit   0-1  Dac_Ext_Sel. Connected to the RS2 and RS3 inputs on the DAC.
  240.         8  Dac_8bit_En. Enables 8bit DAC mode (256colors of 16M) if set
  241.      9-10  Dac_Pix_Dly. Setup and hold time on pixel data. 0: None,
  242.             1: 2ns - 4ns delay, 2: 4ns - 8ns delay
  243.     11-12  Dac_Blank_Adj. Blank Delay in number of pixel clock periods.
  244.             0: None, 1: 1 pixel clock, 2: 2 pixel clocks
  245.        13  Dac_VGA_Adr_En. When bit 24 of Crtc_Gen_Cntl (M+01Ch/1EECh) is set,
  246.            this bit enables access to the VGA DAC I/O addresses (3C6h-3C9h).
  247.     16-18  Dac_Type. The DAC type - initialised from configuration straps on
  248.            power-up. See Config_Stat0 (M+0E4h/72ECh) bits 9-11 for details
  249. */
  250.     _mach64_dac_cntl = get_mach64_port (r.x.cx, r.x.dx, 0x18, 0x31);
  251. /*
  252. M+0E4h/72ECh D(R):  Config_Stat0
  253. bit   0-2  Cfg_Bus_Type. Host Bus type. 0: ISA, 1: EISA, 6: VLB, 7: PCI
  254.       3-5  Cfg_Mem_Type. Memory Type. 0: DRAM (256Kx4), 1: VRAM (256Kx4, x8,
  255.             x16), 2: VRAM (256Kx16 short shift reg), 3: DRAM (256Kx16),
  256.             4: Graphics DRAM (256Kx16), 5: Enh VRAM (256Kx4, x8, x16), 6: Enh
  257.             VRAM (256Kx16 short shift reg)
  258.         6  Cfg_Dual_CAS_En. Dual CAS support enabled if set
  259.       7-8  Cfg_Local_Bus_Option. Local Bus Option.
  260.              1: Local option 1, 2: Local option 2, 3: Local option 3
  261.      9-11  Cfg_Init_DAC_Type. DAC type. 2: ATI68875/TI 34075, 3: Bt476/Bt478,
  262.              4: Bt481, 5: ATI68860/ATI68880, 6: STG1700, 7: SC15021
  263.     12-14  Cfg_Init_Card_ID. Card ID. 0-6: Card ID 0-6, 7: Disable Card ID
  264.        15  Cfg_Tri_Buf_Dis. Tri-stating of output buffers during reset
  265.            disabled if set
  266.     16-21  Cfg_Ext_ROM_Addr. Extended Mode ROM Base Address. Bits 12-17 of the
  267.            ROM base address, 0: C0000h, 1: C1000h ... 3Fh: FE000h
  268.        22  Cfg_ROM_Dis. Disables ROM if set
  269.        23  Cfg_VGA_Enm. Enables VGA Controller
  270.        24  Cfg_Local_Bus_Cfg. 0: Local Bus configuration 2, 1: configuration 1
  271.        25  Cfg_Chip_En. Enables chip if set
  272.        26  Cfg_Local_Read_Dly_Dis. If clear delays read cycle termination by 1
  273.            bus clock, no delay if set
  274.        27  Cfg_ROM_Option. ROM Address. 0: E0000h, 1: C0000h
  275.        28  Cfg_Bus_option. EISA bus: Enables POS registers if set, disables
  276.            POS registers and enables chip if clear.
  277.            VESA Local Bus: Enables decode of I/O address 102h if clear,
  278.            disables if set
  279.        29  Cfg_Local_DAC_Wr_En. Enables local bus DAC writes if set
  280.        30  Cfg_VLB_Rdy_Dis. Disables VESA local bus compliant RDY if set
  281.        31  Cfg_Ap_4Gbyte_Dis. Disables 4GB Aperture Addressing if set
  282. */
  283.     _mach64_config_stat0 = get_mach64_port (r.x.cx, r.x.dx, 0x1c, 0x39);
  284. /*
  285. M+044h/26ECh D(R/W):  Ovr_Wid_Left_Right
  286. bit   0-3  Ovr_Wid_Left. Left overscan width in character clocks
  287.     16-19  Ovr_Wid_Right. Right overscan width in character clocks
  288. */
  289.     _mach64_over_left_right = get_mach64_port (r.x.cx, r.x.dx, 0x09, 0x11);
  290. /*
  291. M+048h/2AECh D(R/W):  Ovr_Wid_Top_Bottom
  292. bit   0-7  Ovr_Wid_Top. Top overscan width in lines
  293.     16-23  Ovr_Wid_Bottom. Bottom overscan width in lines
  294. */
  295.     _mach64_over_top_bott = get_mach64_port (r.x.cx, r.x.dx, 0x0a, 0x12);
  296. /*
  297. M+0B0h/52ECh D(R/W):  Mem_Cntl
  298. bit   0-2  Mem_Size. Video Memory Size. 0: 512K, 1: 1MB, 2: 2MB, 3: 4MB,
  299.             4: 6MB, 5: 8MB
  300.         4  Mem_Rd_Latch_En. Enables latching on RAM port data
  301.         5  Mem_Rd_Latch_Dly. Delays latching of RAM port data by 1/2 memory
  302.            clock period
  303.         6  Mem_Sd_Latch_En. Enables latching of data on serial port data
  304.         7  Mem_Sd_Latch_Dly. Delays latching of serial port data by 1/2 memory
  305.            clock period
  306.         8  Mem_Fill_Pls. One memory clock period set for width of data latch
  307.            pulse
  308.      9-10  Mem_Cyc_Lnth. memory cycle length for non-paged access:
  309.              0: 5 mem clock periods, 1: 6 mem clks, 2: 7 mem clks
  310.     16-17  Mem_Bndry. VGA/Mach Memory boundary. If the memory boundary is
  311.            enabled (bit 18 is set) defines the amount of memory reserved for
  312.            the VGA.  0: 0K, 1: 256K, 2: 512K, 3: 1M
  313.        18  Mem_Bndry_En. If set the video memory is divided between the VGA
  314.            engine and the Mach engine, with the low part reserved for the VGA
  315.            engine, if clear they share the video memory
  316. */
  317.     _mach64_mem_cntl = get_mach64_port (r.x.cx, r.x.dx, 0x14, 0x2c);
  318. /*
  319. M+0E0h/6EECh D(R):  Config_Chip_ID.
  320. bit  0-15  Cfg_Chip_Type. Product Type Code. 0D7h for the 88800GX,
  321.              57h for the 88800CX (guess)
  322.     16-23  Cfg_Chip_Class. Class code
  323.     24-31  Cfg_Chip_Rev. Revision code
  324. */
  325.     _mach64_chip_id = get_mach64_port (r.x.cx, r.x.dx, 0x1b, 0x38);
  326. /* get the chip ID  */
  327.     old = inportl(_mach64_chip_id);
  328.     ChipID = (int)(old & CFG_CHIP_TYPE);
  329.     ChipRev = (int)((old & CFG_CHIP_REV) >> 24);
  330.  
  331.     logerror("15.75KHz: Chip ID :%d\n", ChipID);
  332.     logerror("15.75KHz: Chip Rev :%d\n", ChipRev);
  333.  
  334.     switch (ChipID)
  335.     {
  336.         case MACH64_GX_ID:
  337.             ChipType = MACH64_GX;
  338.             break;
  339.         case MACH64_CX_ID:
  340.             ChipType = MACH64_CX;
  341.             break;
  342.         case MACH64_CT_ID:
  343.             ChipType = MACH64_CT;
  344.             break;
  345.         case MACH64_ET_ID:
  346.             ChipType = MACH64_ET;
  347.             break;
  348.         case MACH64_VT_ID:
  349.         case MACH64_VU_ID:
  350.             ChipType = MACH64_VT;
  351.             break;
  352.         case MACH64_GT_ID:
  353.         case MACH64_GU_ID:
  354.         case MACH64_GP_ID:
  355.         case MACH64_XP_ID:
  356.         case MACH64_XP98_ID:
  357.             ChipType = MACH64_GT;
  358.             break;
  359.         default:
  360.             ChipType=MACH64_UNKNOWN;
  361.     }
  362.  
  363.     logerror("15.75KHz: Chip Type :%d\n", ChipType);
  364. /* and the memory on the card  */
  365.     old = inportl (_mach64_mem_cntl);
  366.     switch (old & MEM_SIZE_ALIAS_GTB)
  367.     {
  368.         case MEM_SIZE_512K:
  369.         case MEM_SIZE_1M:
  370.             MemSize = (int)old & MEM_SIZE_ALIAS_GTB;
  371.             break;
  372.         case MEM_SIZE_2M_GTB:
  373.             MemSize= MEM_SIZE_2M;
  374.             break;
  375.         case MEM_SIZE_4M_GTB:
  376.             MemSize= MEM_SIZE_4M;
  377.             break;
  378.         case MEM_SIZE_6M_GTB:
  379.             MemSize= MEM_SIZE_6M;
  380.             break;
  381.         case MEM_SIZE_8M_GTB:
  382.             MemSize= MEM_SIZE_8M;
  383.             break;
  384.         default:
  385.             MemSize=MEM_SIZE_1M;
  386.     }
  387.     logerror("15.75KHz: Video Memory %d\n", MemSize);
  388. /* and the type of memory  */
  389.     old = inportl(_mach64_config_stat0);
  390.     MemType = old & CFG_MEM_TYPE_xT;
  391.     logerror("15.75KHz: Video Memory  Type %d\n",MemType);
  392.  
  393. #ifdef ATI_PROGRAM_CLOCK
  394. /* only bail out here if the clock's wrong  */
  395. /* so we can collect as much info as possible about the card  */
  396. /* - just in case I ever feel like adding RAMDAC support  */
  397.     if (Clock_Type != CLK_INTERNAL)
  398.     {
  399.         logerror("15.75KHz: Clock type not supported, only internal clocks implemented\n");
  400.         return 0;
  401.     }
  402. #endif
  403.  
  404.     DSPSet=0;
  405.  
  406.     logerror("15.75KHz: Found Mach64 based card with internal clock\n");
  407.     return 1;
  408. }
  409.  
  410. int widthati15KHz(int width)
  411. {
  412. #ifdef ATI_PROGRAM_CLOCK
  413. /* standard width */
  414.     return width;
  415. #else
  416. /* double width scan line */
  417. /* turn off triple buffering */
  418.     use_triplebuf = 0;
  419. /* and return the actual width of the mode */
  420.     return width << 1;
  421. #endif
  422. }
  423.  
  424. int setati15KHz(int vdouble,int width, int height)
  425. {
  426.     int n,extdiv,P;
  427.     int nActualMHz;
  428.     int nHzTotal;
  429.     int nHzDisplay;
  430.     int nHzSyncOffset;
  431.     int nVSyncOffset;
  432.     int nOffSet;
  433.     int interlace;
  434.     int dispdouble;
  435.     long int temp;
  436.     long int gen;
  437. #ifdef ATI_PROGRAM_CLOCK
  438.       int temp1,temp2,temp3;
  439. #endif
  440.     int    lastvisline;
  441.     int    vTotal;
  442.  
  443.     nHzDisplay = inportb (_mach64_crtc_h_total+2);
  444.  
  445.  
  446.     if (!sup_15Khz_res (width, height))
  447.         return 0;
  448. /* last visible line */
  449.     lastvisline = height >> 1;
  450.  
  451. /* get clock and horizontal/vertical totals  */
  452.     if (!calc_mach64_height (vdouble, &nOffSet, &interlace, &dispdouble, &vTotal, &nVSyncOffset, &lastvisline))
  453.         return 0;
  454.  
  455.     if (!calc_mach64_scanline (&nHzTotal, &nHzDisplay, &nHzSyncOffset, &n, &P, &extdiv, &nActualMHz))
  456.         return 0;
  457.     logerror("15.75KHz: Offset:%d ,Interlace:%d ,Dis. Double:%d\n", nOffSet, interlace, dispdouble);
  458.  
  459.     gen = inportl(_mach64_gen_cntrl);
  460.  
  461.  
  462. /* unlock the regs and disable the CRTC */
  463.     outportw (_mach64_gen_cntrl, gen & ~(CRTC_FLAG_lock_regs|CRTC_FLAG_enable_crtc));
  464.  
  465. #ifdef ATI_PROGRAM_CLOCK
  466. /* we need to program the DSP - otherwise we'll get nasty artifacts all over the screen */
  467. /* when we change the clock speed */
  468.     if (((ChipType == MACH64_VT || ChipType == MACH64_GT)&&(ChipRev & 0x07)))
  469.     {
  470.         logerror("15.75KHz: Programming the DSP\n");
  471.         if (!setmach64DSP(0))
  472.         {
  473.             outportl (_mach64_gen_cntrl, gen);
  474.             return 0;
  475.         }
  476.     }
  477.     else
  478.     {
  479.         logerror("15.75KHz: Decided NOT to program the DSP\n");
  480.     }
  481.  
  482. /* now we can program the clock */
  483.     outportb (_mach64_clock_reg + 1, PLL_VCLK_CNTL << 2);
  484.     temp1 = inportb (_mach64_clock_reg + 2);
  485.     outportb (_mach64_clock_reg + 1, (PLL_VCLK_CNTL  << 2) | PLL_WR_EN);
  486.     outportb (_mach64_clock_reg + 2, temp1 | 4);
  487.  
  488.  
  489.     outportb (_mach64_clock_reg + 1, (VCLK_POST_DIV << 2));
  490.     temp2 = inportb (_mach64_clock_reg + 2);
  491.  
  492.  
  493.     outportb (_mach64_clock_reg + 1, ((VCLK0_FB_DIV + CXClk) << 2) | PLL_WR_EN);
  494.     outportb (_mach64_clock_reg +2,n);
  495.  
  496.     outportb (_mach64_clock_reg + 1, (VCLK_POST_DIV << 2) | PLL_WR_EN);
  497.     outportb (_mach64_clock_reg + 2, (temp2 & ~(0x03 << (2 * CXClk))) | (P << (2 * CXClk)));
  498.  
  499.     outportb (_mach64_clock_reg + 1, PLL_XCLK_CNTL << 2);
  500.     temp3 = inportb (_mach64_clock_reg + 2);
  501.     outportb (_mach64_clock_reg + 1, (PLL_XCLK_CNTL << 2) | PLL_WR_EN);
  502.  
  503.     if (extdiv)
  504.         outportb (_mach64_clock_reg + 2, temp3 | (1 << (CXClk + 4)));
  505.     else
  506.         outportb (_mach64_clock_reg + 2, temp3 & ~(1 << (CXClk + 4)));
  507.  
  508.  
  509.  
  510.     outportb (_mach64_clock_reg + 1, (PLL_VCLK_CNTL << 2) | PLL_WR_EN);
  511.     outportb (_mach64_clock_reg + 2, temp1&~0x04);
  512.  
  513. /* reset the DAC */
  514.     inportb (_mach64_dac_cntl);
  515. #endif
  516.  
  517.     logerror("15.75KHz: H total %d, H display %d, H sync offset %d\n",nHzTotal,nHzDisplay,nHzSyncOffset);
  518.     logerror("15.75KHz: V total %d, V display %d, V sync offset %d\n",vTotal,lastvisline,nVSyncOffset);
  519.  
  520. /* now setup the CRTC timings */
  521.  
  522.     outportb (_mach64_crtc_h_total, nHzTotal);  /* h total */
  523.     outportb (_mach64_crtc_h_total + 2, nHzDisplay); /* h display width */
  524.     outportb (_mach64_crtc_h_sync, nHzDisplay+nHzSyncOffset + center_x);   /* h sync start */
  525.     outportb (_mach64_crtc_h_sync + 1, 0);  /* h sync delay */
  526. #ifdef ATI_PROGRAM_CLOCK
  527.     outportb (_mach64_crtc_h_sync + 2, 12); /* h sync width */
  528. #else
  529.     outportb (_mach64_crtc_h_sync + 2, 20); /* h sync width */
  530. #endif
  531.     outportw (_mach64_crtc_v_total, (vTotal<<interlace));   /* v total */
  532.     outportw (_mach64_crtc_v_total + 2, (lastvisline<<interlace)-1);  /* v display height */
  533.     outportw (_mach64_crtc_v_sync, ((lastvisline+nVSyncOffset)<<interlace) + center_y);    /* v sync start */
  534.     outportb (_mach64_crtc_v_sync + 2, 3);          /* v sync width */
  535.  
  536. /* make sure sync is negative */
  537.     temp = inportl(_mach64_crtc_h_sync);
  538.     temp |= CRTC_H_SYNC_NEG;
  539.     outportl (_mach64_crtc_h_sync,temp);
  540.  
  541.     temp = inportl(_mach64_crtc_v_sync);
  542.     temp |= CRTC_V_SYNC_NEG;
  543.       outportl (_mach64_crtc_v_sync,temp);
  544.  
  545. /* clear any overscan */
  546.     outportb (_mach64_over_left_right,0);
  547.     outportb (_mach64_over_left_right+2,0);
  548.     outportb (_mach64_over_top_bott,0);
  549.     outportb (_mach64_over_top_bott+2,0);
  550.  
  551. /* set memory for each line */
  552.     temp = inportl(_mach64_off_pitch);
  553.     temp &= 0xfffff;
  554.     outportl (_mach64_off_pitch,temp|(nOffSet<<22));
  555.  
  556. /* max out the FIFO */
  557.     gen |= (15<<16);
  558.  
  559. /* turn on/off interlacing */
  560.       if (interlace)
  561.         gen |= CRTC_Enable_Interlace;
  562.       else
  563.         gen &=~ CRTC_Enable_Interlace;
  564. /* set the interlace flag */
  565.     setinterlaceflag (interlace);
  566. /* turn off scanline doubling if we need to */
  567.     if (dispdouble)
  568.         gen &=~ CRTC_Enable_Doubling;
  569.  
  570. /* set the display going again */
  571.     outportl (_mach64_gen_cntrl,gen);
  572. /* finally select and strobe the clock */
  573.     outportb (_mach64_clock_reg, CXClk | CLOCK_STROBE);
  574.     return 1;
  575. }
  576.  
  577. void resetati15KHz()
  578. {
  579. /* reset the DSP */
  580.     resetmach64DSP();
  581. /* it could be a bit risky resetting the clock + general registers if we're running on an arcade monitor */
  582. /* so, I'll leave 'em for the moment */
  583. }
  584.  
  585. int calc_mach64_height(int vdouble,int *nOffSet,int *interlace,int *dispdouble,int *vTotal,int *nVSyncOffset,int *nlastline)
  586. {
  587.     int nVtDispTotal;
  588.     long int lport;
  589.     long int temp;
  590.  
  591. /* get the current visible display total */
  592.     nVtDispTotal = getVtEndDisplay();
  593. /* assume it's hires and we're :-  */
  594. /* going to interlace, not alter scanline doubling, and not change the offset */
  595.     *interlace = 1;
  596.     *dispdouble = 0;
  597.     temp = inportl (_mach64_off_pitch);
  598.     temp >>= 22;
  599.     *nOffSet = temp;
  600.     *vTotal = 0;
  601.  
  602.  
  603.     switch (nVtDispTotal)
  604.     {
  605.         case 479:    /* 640x480 */
  606.             *vTotal = 256 + tw640x480arc_v;
  607.             *nVSyncOffset = 2;
  608.             if (vdouble)
  609.             {
  610.                 logerror("15.75KHz: Mode is using software doubling, disabling interlace and halfing y res\n");
  611.                 *interlace = 0;
  612. /* only draw every other line */
  613.                 *nOffSet <<= 1;
  614.             }
  615.             else
  616.             {
  617. /* check if the mode was set up with internal scan line doubling */
  618.                 lport = inportl(_mach64_gen_cntrl);
  619.                 if (lport & CRTC_Enable_Doubling)
  620.                 {
  621.                     logerror("15.75KHz: Mode is using hardware doubling, disabling interlace, disabling hardware doubling\n");
  622.                     *interlace = 0;
  623.                     *dispdouble = 1;
  624.                 }
  625.             }
  626.             break;
  627.         default:    /* unhandled resolution */
  628.             logerror("15.75KHz: Unsupported SVGA 15.75KHz height (%d)\n", nVtDispTotal+1);
  629.             return 0;
  630.  
  631.     }
  632.     return 1;
  633. }
  634.  
  635. int calc_mach64_scanline(int *nHzTotal,int *nHzDispTotal,int *nHzSyncOffset,int *N,int *P,int *externaldiv,int *nActualMHz)
  636. {
  637. /* set clock and horizontal Total based on Horizontal display width */
  638. /* NOTE: Only 640x480 so far, */
  639. /* 320x240 has a very low clock width and even with the slowest clock speed has a 'bad' aspect ratio */
  640. /* doubled 640x480 looks a lot better and runs about as fast */
  641. /* higher resolutions just result in more and more overscan */
  642.  
  643.     int nTargetHzTotal, nActualHzTotal;
  644.     int nTargetMHz=0;
  645. /* get the horizontal width */
  646.     *nHzDispTotal = inportb (_mach64_crtc_h_total + 2);
  647.     switch (*nHzDispTotal)
  648.     {
  649.         case 79: /* 640x480 */
  650.             logerror("15.75KHz: 640x480 mode Attempting to use 14MHz Clock\n");
  651.             nTargetMHz = 1400;
  652.             nTargetHzTotal = tw640x480arc_h - 83;
  653.             *nHzSyncOffset = 6;
  654.             break;
  655.         default: /* unhandled res, return error */
  656.             logerror("15.75KHz: Unsupported SVGA 15.75KHz mode (%d chars)\n", *nHzDispTotal);
  657.  
  658.             return 0;
  659.     }
  660. #ifdef ATI_PROGRAM_CLOCK
  661. /* calculate the clock */
  662.     *nActualMHz = calc_mach64_clock (nTargetMHz, N, P, externaldiv);
  663. /* adjust the horizontal total */
  664.     nActualHzTotal = (int)(((float)nTargetHzTotal / (float)nTargetMHz) * (float)*nActualMHz);
  665.     logerror("15.75KHz: tgt MHz:%d, act MHz:%d, tgt HzTot:%d, act HzTot:%d\n",
  666.                 nTargetMHz, *nActualMHz, nTargetHzTotal, nActualHzTotal);
  667. #else
  668. /* not programming the clock, so setup a double width scan line */
  669.     *nActualMHz = 0;
  670.     nActualHzTotal = tw640x480arc_h + 5;
  671.     *nHzDispTotal = (*nHzDispTotal * 2) + 1;
  672.     *nHzSyncOffset = 0;
  673.     logerror("15.75KHz: HzTot:%d\n", nActualHzTotal);
  674.  
  675. #endif
  676.  
  677.     *nHzTotal = nActualHzTotal;
  678.     return 1;
  679. }
  680.  
  681. int calc_mach64_clock(int nTargetMHz,int *N,int *P,int *externaldiv)
  682. {
  683.  
  684.     int postDiv;
  685.     int nActualMHz;
  686.     float Q;
  687.  
  688. /* assume the best */
  689.     nActualMHz = nTargetMHz;
  690. /* check clock is in range */
  691.     if (nActualMHz < MinFreq)
  692.         nActualMHz = MinFreq;
  693.  
  694.     if (nActualMHz > MaxFreq)
  695.         nActualMHz = MaxFreq;
  696. /* formula for clock is as follows */
  697. /* Clock = ((2 * mach64RefFreq * N)/(mach64RefDivider * postDiv)) */
  698.  
  699.  
  700.     Q = (nActualMHz * RefDivider)/(2.0 * RefFreq);
  701.     logerror("15.75KHz: Q:%d\n", (int)Q);
  702.     *externaldiv = 0;
  703.  
  704.     if (Q > 255)
  705.     {
  706.         logerror("15.75KHz: Q too big\n");
  707.         Q = 255;
  708.         *P = 0;
  709.         postDiv = 1;
  710.     }
  711.     else if (Q > 127.5)
  712.     {
  713.         *P = 0;
  714.         postDiv = 1;
  715.     }
  716.     else if (Q > 85)
  717.     {
  718.         *P = 1;
  719.         postDiv = 2;
  720.     }
  721.     else if (Q > 63.75)
  722.     {
  723.         *P = 0;
  724.         postDiv = 3;
  725.         *externaldiv = 1;
  726.     }
  727.     else if (Q > 42.5)
  728.     {
  729.         *P = 2;
  730.         postDiv = 4;
  731.     }
  732.     else if (Q > 31.875)
  733.     {
  734.         *P = 2;
  735.         postDiv = 6;
  736.         *externaldiv = 1;
  737.     }
  738.     else if (Q > 21.25)
  739.     {
  740.         *P = 3;
  741.         postDiv = 8;
  742.     }
  743.     else if (Q >= 10.6666666667)
  744.     {
  745.         *P = 3;
  746.         postDiv = 12;
  747.         *externaldiv = 1;
  748.     }
  749.     else
  750.     {
  751.         *P = 3;
  752.         postDiv = 12;
  753.         *externaldiv = 1;
  754.     }
  755.     *N = (int)(Q * postDiv + 0.5);
  756.  
  757.     nActualMHz = ((2 * RefFreq * (*N)) / (RefDivider * postDiv));
  758.  
  759.  
  760.     logerror("15.75KHz: MACH64 N val:%d\n", *N);
  761.     logerror("15.75KHz: MACH64 Post Div val:%d\n", *P);
  762.     logerror("15.75KHz: MACH64 external div:%d\n", *externaldiv);
  763.  
  764.     return nActualMHz;
  765. }
  766.  
  767.  
  768. int get_mach64_port(int io_type, int io_base, int io_sel, int mm_sel)
  769. {
  770.     if (io_type)
  771.     {
  772.         return (mm_sel << 2) + io_base;
  773.     }
  774.     else
  775.     {
  776.         if (!io_base)
  777.             io_base = 0x2EC;
  778.         return (io_sel << 10) + io_base;
  779.     }
  780. }
  781.  
  782.  
  783.  
  784. int setmach64DSP(int nAdd)
  785. {
  786.     unsigned short dsp_on, dsp_off, dsp_xclks_per_qw, dsp_prec, loop_latency;
  787.     long portval;
  788.     static int offset=0;
  789.  
  790.     offset+=nAdd;
  791. /* okay, I've been unable to get any reliable information about the DSP */
  792. /* so these are just values that work for this :- */
  793. /* dot clock speed, colour depth and video clock speed */
  794. /* found after a bit of hacking around */
  795. /*- The memory stuff is probably real though */
  796.  
  797. /* get the colour depth */
  798.     portval = inportb (_mach64_gen_cntrl+1) & 7;
  799.  
  800.     switch (portval)
  801.     {
  802.         case  2: /* 8 bit colour */
  803.             switch (VRAMMemClk)
  804.             {
  805.                 /* 100MHz -  for newer/faster cards */
  806.                 case 10000:
  807.                     dsp_xclks_per_qw = 2239+offset;
  808.                     break;
  809.                 /* Standard video memory speed (usually 60MHz)*/
  810.                 default:
  811.                     dsp_xclks_per_qw = 2189+offset;
  812.             }
  813.             logerror("DSP value %d (8bit)\n",dsp_xclks_per_qw);
  814.  
  815.             break;
  816.         case  3: /* 16 bit colour */
  817.         case  4: /* either 555 or 565 */
  818.             switch (VRAMMemClk)
  819.             {
  820.                 /* 100MHz -  for newer/faster cards */
  821.                 case 10000:
  822.                     dsp_xclks_per_qw = 3655+offset;
  823.                     break;
  824.                 /* Standard video memory speed (usually 60MHz)*/
  825.                 default:
  826.                     dsp_xclks_per_qw = 3679+offset;
  827.             }
  828.             logerror("DSP value %d (16bit)\n",dsp_xclks_per_qw);
  829.  
  830.             break;
  831.         default: /* any other colour depth */
  832.             logerror("15.75KHz: Unsupported colour depth for ATI driver (%d)\n",(int)inportb (_mach64_gen_cntrl+1));
  833.             return 0;
  834.     }
  835.  
  836.  
  837.     if (MemSize > MEM_SIZE_1M)
  838.     {
  839.         if (MemType >= SDRAM)
  840.             loop_latency = 8;
  841.         else
  842.             loop_latency = 6;
  843.     }
  844.     else
  845.     {
  846.         if (MemType >= SDRAM)
  847.             loop_latency = 9;
  848.         else
  849.             loop_latency = 8;
  850.     }
  851.  
  852. /* our DSP values */
  853.     dsp_on = 106;
  854.     dsp_off = 206;
  855.     dsp_prec = 5;
  856.  
  857.     logerror("15.75KHz: DSP on:%d DSP off:%d DSP clks :%d  DSP prec:%d  latency :%d\n", (int)dsp_on, (int)dsp_off,
  858.                 (int)dsp_xclks_per_qw, (int)dsp_prec, (int)loop_latency);
  859. /* save whats there */
  860.     SaveDSPOnOff = inportw (_mach64_dsp_on_off);
  861.     SaveDSPConfig = inportw (_mach64_dsp_on_off);
  862.  
  863. /* write everything out */
  864.     outportw (_mach64_dsp_on_off, ((dsp_on << 16) & DSP_ON) | (dsp_off & DSP_OFF));
  865.     outportw (_mach64_dsp_config, ((dsp_prec << 20) & DSP_PRECISION) | ((loop_latency << 16) & DSP_LOOP_LATENCY)
  866.                 | (dsp_xclks_per_qw & DSP_XCLKS_PER_QW));
  867.     DSPSet = 1;
  868.  
  869.     return dsp_xclks_per_qw;
  870. }
  871.  
  872.  
  873. void resetmach64DSP()
  874. {
  875.     if(DSPSet)
  876.     {
  877.         outportw (_mach64_dsp_on_off, SaveDSPOnOff);
  878.         outportw (_mach64_dsp_config, SaveDSPConfig);
  879.     }
  880. }
  881.  
  882.  
  883.